package com.net.xpay.openapi.controller.openapi.safepay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayFundAccountbookCloseResponse;
import com.alipay.api.response.AlipayFundAccountbookQueryResponse;
import com.alipay.api.response.AlipayUserAgreementUnsignResponse;
import com.beust.jcommander.internal.Lists;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.net.xpay.common.domain.BookAccountTransferOrder;
import com.net.xpay.common.domain.SafePayBusinessAuthAuditRecord;
import com.net.xpay.common.domain.SafePayOrderReceipt;
import com.net.xpay.common.domain.User;
import com.net.xpay.common.manager.BookAccountTransferOrderManager;
import com.net.xpay.common.manager.SafePayBusinessAuthAuditRecordManager;
import com.net.xpay.common.manager.SafePayOrderReceiptManager;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.core.model.*;
import com.net.xpay.openapi.aop.OpenApi;
import com.net.xpay.openapi.dto.*;
import com.net.xpay.openapi.helper.ImageIdHelper;
import com.net.xpay.openapi.model.*;
import com.net.xpay.openapi.protocol.OpenApiBase;
import com.net.xpay.openapi.protocol.OpenApiProtocol;
import com.net.xpay.openapi.protocol.OpenApiResult;
import com.net.common.exception.BusinessException;
import com.net.xpay.common.domain.openapi.OpenApp;
import com.net.xpay.common.manager.openapi.OpenAppManager;
import com.net.xpay.core.enums.SafePayBookAccountSignStatus;
import com.net.xpay.openapi.dto.*;
import com.net.xpay.openapi.model.*;
import com.net.xpay.core.service.safePay.SafePayBookAccountService;
import com.net.common.util.AlipayAccountCheckUtil;
import com.net.common.util.MoneyUtil;
import com.net.common.util.SerializationUtil;
import com.net.xpay.alipay.safePay.PoseidonSafePayAlipayClient;
import com.net.xpay.common.annotation.ApiMonitoring;
import com.net.xpay.common.enums.safePay.ApplyReceiptStatus;
import com.net.xpay.common.enums.safePay.UniTransStatus;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.domain.UserAccount;
import com.net.xpay.core.domain.safePay.BookAccountChargeOrder;
import com.net.xpay.core.domain.safePay.SafePayBatch;
import com.net.xpay.core.domain.safePay.SafePayBookAccount;
import com.net.xpay.core.domain.safePay.SafePayOrder;
import com.net.xpay.core.enums.SafePayBatchStatus;
import com.net.xpay.core.enums.SafePayOrderStatus;
import com.net.xpay.core.manager.UserAccountManager;
import com.net.xpay.core.manager.safePay.BookAccountChargeOrderManager;
import com.net.xpay.core.manager.safePay.SafePayBatchManager;
import com.net.xpay.core.manager.safePay.SafePayBookAccountManager;
import com.net.xpay.core.manager.safePay.SafePayOrderManager;
import com.net.xpay.core.service.safePay.SafePayReceiptService;
import com.net.xpay.core.service.safePay.SafePayService;
import com.net.xpay.core.utils.BeanCopierUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

@RestController
@Slf4j
@RequestMapping("/apiv1/openapi/safe-payment")
@Api(tags = "第三方开放调用/安全发", description = "第三方开放调用 安全发 net")
public class OpenApiSafePayController extends OpenApiBase {
    @Autowired
    private PoseidonSafePayAlipayClient xpaySafePayAlipayClient;

    @Autowired
    private SafePayBookAccountManager safePayBookAccountManager;

    @Autowired
    private SafePayService safePayService;

    @Autowired
    private SafePayBatchManager safePayBatchManager;

    @Autowired
    private SafePayOrderManager safePayOrderManager;

    @Autowired
    private BookAccountChargeOrderManager bookAccountChargeOrderManager;

    @Autowired
    private UserAccountManager userAccountManager;

    @Autowired
    private SafePayReceiptService safePayReceiptService;

    @Autowired
    private SafePayOrderReceiptManager safePayOrderReceiptManager;

    @Autowired
    private BookAccountTransferOrderManager bookAccountTransferOrderManager;

    @Autowired
    private SafePayBookAccountService safePayBookAccountService;

    @Autowired
    private SafePayBusinessAuthAuditRecordManager safePayBusinessAuthAuditRecordManager;

    @Autowired
    private ImageIdHelper imageIdHelper;

    @Autowired
    private UserManager userManager;

    @Autowired
    private OpenAppManager openAppManager;


    /**
     * 签约，获取签约链接
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/签约")
    @ApiOperation(value = "签约，获取签约链接")
    @PostMapping("/sign")
    @ResponseBody
    public OpenApiResult<OpenApiSafePaySignDto> getOpenSignPage(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePaySignModel authModel = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePaySignModel.class);

        if (Strings.isNullOrEmpty(authModel.getAlipayNickName())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "请输入支付宝账号");
        }

        authModel.setAlipayNickName(authModel.getAlipayNickName());
        User user = userManager.getById(openApp.getUserId());
        SafePayPageSignModel signModel = new SafePayPageSignModel();
        signModel.setAlipayName(authModel.getAlipayName());
        signModel.setAlipayNickName(authModel.getAlipayNickName());

        OpenApiSafePaySignDto dto = new OpenApiSafePaySignDto();
        dto.setSignUrl(safePayService.getSignPage(user, signModel));
        return new OpenApiResult<>(dto);
    }

    /**
     * 解约支付宝账号
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/解约")
    @ApiOperation("解约支付宝账号")
    @PostMapping("/unsign")
    public OpenApiResult<OpenApiSafePayUnsignDto> unsignSafePayBookAccount(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayUnsignModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayUnsignModel.class);

        if (Strings.isNullOrEmpty(model.getAlipayNickName())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "请传入支付宝账号");
        }
        User user = userManager.getById(openApp.getUserId());

        SafePayBookAccount safePayBookAccount = safePayBookAccountManager.findByAlipayNickName(user.getId(), model.getAlipayNickName());
        if (safePayBookAccount == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "支付宝账户不存在");
        }
        if (safePayBookAccount.getSignStatus() != SafePayBookAccountSignStatus.NORMAL) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "支付宝账户已解约");
        }

        //余额不为0暂时不能解除
        try {
            AlipayFundAccountbookQueryResponse resp;
            resp = xpaySafePayAlipayClient.queryAlipayFundAccountbook(safePayBookAccount.getBookId(), safePayBookAccount.getAgreementNo());
            if (resp.isSuccess()) {
                if (new BigDecimal(resp.getAvailableAmount()).compareTo(new BigDecimal("0")) > 0) {
                    throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "账户本金余额不为0，暂无法解约");
                }
            }
        } catch (AlipayApiException ignored) {
        }

        //注销
        try {
            AlipayFundAccountbookCloseResponse alipayFundAccountbookCloseResponse = xpaySafePayAlipayClient.closeAlipayFundAccountbook(safePayBookAccount.getBookId(), safePayBookAccount.getAgreementNo());
            if (!alipayFundAccountbookCloseResponse.isSuccess()) {
                log.info("closeAlipayFundAccountbook failed|resp={}", SerializationUtil.obj2String(alipayFundAccountbookCloseResponse));
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "注销失败：" + alipayFundAccountbookCloseResponse.getMsg() + "|" + alipayFundAccountbookCloseResponse.getSubMsg());
            }
            log.info("closeAlipayFundAccountbook success|resp={}", SerializationUtil.obj2String(alipayFundAccountbookCloseResponse));
        } catch (AlipayApiException e) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "系统繁忙");
        }

        try {
            AlipayUserAgreementUnsignResponse resp = xpaySafePayAlipayClient.unSignAlipayUserAgreement(safePayBookAccount.getExternalAgreementNo());
            if (!resp.isSuccess()) {
                log.warn("unsignAlipayUser failed|userId={}|account={}|errorCode={}|errorMsg={}", user.getId(), safePayBookAccount.getAlipayNickName(), resp.getCode() + "|" + resp.getSubCode(), resp.getMsg() + "|" + resp.getSubMsg());
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "解约失败：" + resp.getMsg() + ";" + resp.getSubMsg());
            }
        } catch (AlipayApiException e) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "系统繁忙");
        }

        safePayBookAccount.setSignStatus(SafePayBookAccountSignStatus.STOP);
        safePayBookAccountManager.updateByPrimaryKeyWithVersion(safePayBookAccount);
        OpenApiSafePayUnsignDto dto = new OpenApiSafePayUnsignDto();
        dto.setSuccess(true);
        return new OpenApiResult<>(dto);
    }


    /**
     * 查询安全付支付宝签约和实名认证结果
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/查询安全付支付宝签约和实名认证结果")
    @ApiOperation("查询安全付支付宝签约和实名认证结果")
    @PostMapping("/query-sign-result")
    public OpenApiResult<OpenApiSafePaySignResultQueryDto> querySignResult(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePaySignQueryModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePaySignQueryModel.class);

        if (Strings.isNullOrEmpty(model.getAlipayNickName())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "请输入支付宝账号");
        }

        User user = userManager.getById(openApp.getUserId());

        SafePayBookAccount safePayBookAccount = safePayBookAccountManager.findByAlipayNickName(user.getId(), model.getAlipayNickName());
        if (safePayBookAccount == null) {
            throw new BusinessException(PoseidonErrorCode.ALIPAY_USER_NO_EXIST, "该用户尚未发起签约");
        }
        OpenApiSafePaySignResultQueryDto dto = OpenApiSafePaySignResultQueryDto.getInstance();
        dto.setAlipayNickName(safePayBookAccount.getAlipayNickName());
        dto.setStatus(safePayBookAccount.getSignStatus());
        dto.setBookId(safePayBookAccount.getBookId());
        dto.setAgreementNo(safePayBookAccount.getAgreementNo());
        dto.setAuditStatus(safePayBookAccount.getAuditStatus());
        dto.setExtCardInfo(safePayBookAccount.getExtCardInfo());
        return new OpenApiResult<>(dto);
    }

    /**
     * 企业实名认证
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/企业实名认证")
    @ApiOperation("企业实名认证")
    @PostMapping("/submit-business-authentication")
    public OpenApiResult<OpenApiSafePayBusinessAuthenticationSubmitDto> submitBusinessAuthentication(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayBusinessAuthenticationSubmitModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayBusinessAuthenticationSubmitModel.class);

        User user = userManager.getById(openApp.getUserId());
        SafePayBookAccountSubmitBusinessAuthModel authModel = new SafePayBookAccountSubmitBusinessAuthModel();
        authModel.setAlipayNickName(model.getAlipayNickName());
        authModel.setBusinessLicense(model.getBusinessName());
        authModel.setIcpInfo(model.getIcpInfo());
        //图片链接需要转换
        authModel.setIdCardFront(imageIdHelper.fetchImageUrl(model.getIdCardFrontImageId()));
        authModel.setBizLicense(imageIdHelper.fetchImageUrl(model.getBizLicenseImageId()));
        authModel.setBusinessLicense(imageIdHelper.fetchImageUrl(model.getBusinessLicenseImageId()));
        authModel.setIdCardBack(imageIdHelper.fetchImageUrl(model.getIdCardBackImageId()));
        authModel.setBizSceneDesc(imageIdHelper.fetchImageUrl(model.getBizSceneDescImageId()));
        authModel.setMerchantCommitment(imageIdHelper.fetchImageUrl(model.getMerchantCommitmentImageId()));
        authModel.setOfficeImages(imageIdHelper.fetchImageUrls(Lists.newArrayList(model.getOfficeImage1ImageId(), model.getOfficeImage2ImageId())));
        authModel.setOtherOneImages(imageIdHelper.fetchImageUrl(model.getOther1ImageId()));
        authModel.setOtherTwoImages(imageIdHelper.fetchImageUrl(model.getOther2ImageId()));
        authModel.setOtherThreeImages(imageIdHelper.fetchImageUrl(model.getOther3ImageId()));
        SafePayBusinessAuthAuditRecord record = safePayBookAccountService.submitBusinessAuthentication(user, authModel);

        OpenApiSafePayBusinessAuthenticationSubmitDto dto = new OpenApiSafePayBusinessAuthenticationSubmitDto();
        dto.setId(record.getId().toString());
        return new OpenApiResult<>(dto);
    }

    /**
     * 查询企业实名认证结果
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/查询企业实名认证结果")
    @ApiOperation("查询企业实名认证结果")
    @PostMapping("/query-business-authentication")
    public OpenApiResult<OpenApiBusinessAuthenticationQueryDto> queryBusinessAuthentication(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayBusinessAuthenticationQueryModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayBusinessAuthenticationQueryModel.class);

        SafePayBusinessAuthAuditRecord record = safePayBusinessAuthAuditRecordManager.findById(openApp.getUserId(), model.getId());
        if (record == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "企业实名认证记录不存在");
        }
        OpenApiBusinessAuthenticationQueryDto dto = new OpenApiBusinessAuthenticationQueryDto();
        dto.setId(record.getId());
        dto.setAlipayNickName(record.getAlipayNickName());
        dto.setAuditStatus(record.getAuditStatus());
        dto.setAuditMessage(record.getAuditMessage());
        return new OpenApiResult<>(dto);
    }

    /**
     * 批量代发到支付宝
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/批量代发到支付宝")
    @ApiOperation(value = "批量代发到支付宝")
    @PostMapping("/create-order-batch")
    @ResponseBody
    public OpenApiResult<OpenApiSafePayBatchCreateDto> createSafePayBatch(@RequestBody OpenApiProtocol openApiProtocol) {
        long t1 = System.currentTimeMillis();
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayBatchCreateModel batchModel = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayBatchCreateModel.class);
        if (batchModel.getConfirmTrans() == null || batchModel.getConfirmTrans() != 1) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "confirmTrans请传固定值1");
        }
        User user = userManager.getById(openApp.getUserId());
        batchModel.setNeedNotify(true);//默认需要推送
        SafePayBatchCreateModel createModel = new SafePayBatchCreateModel();
        BeanCopierUtil.copy(batchModel, createModel);

        List<SafePayTransModel> payTrans = BeanCopierUtil.batchCopy(OpenApiSafePayTransModel.class, SafePayTransModel.class, batchModel.getPayTrans());
        createModel.setPayTrans(payTrans);
        createModel.setAppId(openApp.getId());
        SafePayBatch batch = safePayService.createSafePayBatch(user, createModel);
        long t2 = System.currentTimeMillis();
        OpenApiSafePayBatchCreateDto safePayBatchDto = new OpenApiSafePayBatchCreateDto();
        BeanCopierUtil.copy(batch, safePayBatchDto);
        log.info("createSafePayBatch end|params={}|cost={}", SerializationUtil.obj2String(batchModel), t2 - t1);
        return new OpenApiResult<>(safePayBatchDto);
    }

    /**
     * 同步下载回单
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/同步下载回单")
    @ApiOperation("同步下载回单")
    @PostMapping("/sync-apply-receipt")
    public OpenApiResult<OpenApiSafePayOrderReceiptSyncApplyDto> syncApplyOrderReceipt(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayOrderReceiptSyncApplyModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayOrderReceiptSyncApplyModel.class);

        if (Strings.isNullOrEmpty(model.getImportBatchNo())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "外部批次号不能为空");
        }
        if (Strings.isNullOrEmpty(model.getImportBizNo())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "明细外部订单号不能为空");
        }

        User user = userManager.getById(openApp.getUserId());
        SafePayOrder order = safePayOrderManager.findByImportBizNo(user.getId(), model.getImportBatchNo(), model.getImportBizNo());
        if (order == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "订单不存在");
        }
        if (order.getStatus() != SafePayOrderStatus.SUCCESS) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "订单未转账成功，无法下载回单");
        }
        Preconditions.checkArgument(order.getUserId().equals(user.getId()));

        SafePayOrderReceipt receipt = safePayReceiptService.applySafePayOrderBillFile(user, order.getId());

        //目前发现回单生成很快，而且过期很快大概1分钟，所以直接同步返回结果
        LocalDateTime deadline = LocalDateTime.now().plusSeconds(20L);
        while (LocalDateTime.now().isBefore(deadline)) {
            try {
                receipt = safePayReceiptService.updateReceiptFile(receipt.getId());
                if (receipt.getStatus() == ApplyReceiptStatus.SUCCESS) {

                    OpenApiSafePayOrderReceiptSyncApplyDto dto = new OpenApiSafePayOrderReceiptSyncApplyDto();
                    dto.setDownloadReceiptUrl(receipt.getDownloadUrl());
                    return new OpenApiResult<>(dto);
                }
            } catch (Exception e) {
                log.warn("syncApplyOrderReceipt error|id={}", receipt.getId(), e);
            }
        }
        //超时设置为失败，让重新下载
        receipt.setStatus(ApplyReceiptStatus.FAIL);
        safePayOrderReceiptManager.update(receipt);

        throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "下载超时，请稍后再试");
    }

    /**
     * 记账本之间相互调拨
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/记账本之间相互调拨")
    @ApiOperation("记账本之间相互调拨")
    @PostMapping("/book-account-transfer")
    public OpenApiResult<OpenApiSafePayBookAccountTransferDto> transferBookAccount(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));

        OpenApiSafePayBookAccountTransferModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayBookAccountTransferModel.class);
        User user = userManager.getById(openApp.getUserId());
        BookAccountTransferOrderModel orderModel = new BookAccountTransferOrderModel();
        BeanCopierUtil.copy(model, orderModel);
        BookAccountTransferOrder order = safePayService.transferBookAccount(user, orderModel);
        OpenApiSafePayBookAccountTransferDto dto = new OpenApiSafePayBookAccountTransferDto();
        dto.setImportBizNo(order.getImportBizNo());
        dto.setOrderId(order.getOrderId());
        dto.setPayFundOrderId(order.getPayFundOrderId());
        dto.setTransDate(order.getTransDate());
        return new OpenApiResult<>(dto);
    }


    /**
     * 查询记账本调拨记录
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/查询记账本调拨记录")
    @ApiOperation("查询记账本调拨记录")
    @PostMapping("/query-book-account-trans-order")
    public OpenApiResult<OpenApiSafePayBookAccountTransOrderQueryDto> queryBookAccountTransferOrder(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));

        OpenApiSafePayBookAccountTransOrderQueryModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayBookAccountTransOrderQueryModel.class);
        if (Strings.isNullOrEmpty(model.getImportBizNo())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "外部订单号不能为空");
        }

        User user = userManager.getById(openApp.getUserId());
        BookAccountTransferOrder order = bookAccountTransferOrderManager.findByImportBizNo(user.getId(), model.getImportBizNo());
        if (order == null || order.getStatus() != UniTransStatus.SUCCESS) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "订单不存在");
        }
        OpenApiSafePayBookAccountTransOrderQueryDto dto = new OpenApiSafePayBookAccountTransOrderQueryDto();
        dto.setImportBizNo(order.getImportBizNo());
        dto.setOrderId(order.getOrderId());
        dto.setPayFundOrderId(order.getPayFundOrderId());
        dto.setTransDate(order.getTransDate());
        return new OpenApiResult<>(dto);
    }

    /**
     * 查询余额 单位元 精确到2位小数
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/查询账户余额")
    @ApiOperation(value = "查询账户余额")
    @PostMapping("/get-balance")
    public OpenApiResult<OpenApiSafePayBalanceGetDto> getBalance(@RequestBody OpenApiProtocol openApiProtocol) throws AlipayApiException {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayBalanceGetModel authModel = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayBalanceGetModel.class);

        User user = userManager.getById(openApp.getUserId());
        UserAccount userAccount = userAccountManager.getById(user.getId());
        OpenApiSafePayBalanceGetDto dto = OpenApiSafePayBalanceGetDto.getInstance();
        dto.setBalance(MoneyUtil.convertCentToString(userAccount.getMoneyLeft(), 2));
        dto.setAlipayNickName(authModel.getAlipayNickName());

        if (!Strings.isNullOrEmpty(authModel.getAlipayNickName())) {
            dto.setAlipayNickName(authModel.getAlipayNickName());
            SafePayBookAccount safePayBookAccount = safePayBookAccountManager.findByAlipayNickName(user.getId(), authModel.getAlipayNickName());
            if (safePayBookAccount == null) {
                dto.setBookBalance("0.00");
            } else {
                AlipayFundAccountbookQueryResponse resp = xpaySafePayAlipayClient.queryAlipayFundAccountbook(safePayBookAccount.getBookId(), safePayBookAccount.getAgreementNo());
                if (resp.isSuccess()) {
                    dto.setBookBalance(resp.getAvailableAmount());
                } else {
                    log.info("safePay getBalance failed safePayBookAccount={}|resp={}", SerializationUtil.obj2String(safePayBookAccount), resp.getCode() + "|" + resp.getMsg() + "|" + resp.getSubCode() + "|" + resp.getSubMsg());
                    throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "余额查询失败请重试");
                }
            }
        }
        return new OpenApiResult<>(dto);
    }

    /**
     * 查询批量代发结果
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/查询批量代发结果")
    @ApiOperation("查询批量代发结果")
    @PostMapping("/query-batch-result")
    public OpenApiResult<OpenApiSafePayBatchResultQueryDto> queryBatchResult(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));

        OpenApiSafePayBatchResultQueryModel queryModel = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayBatchResultQueryModel.class);

        if (Strings.isNullOrEmpty(queryModel.getImportBatchNo())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "批次号不能为空");
        }

        User user = userManager.getById(openApp.getUserId());
        SafePayBatch batch = safePayBatchManager.findByImportBatchNo(user.getId(), queryModel.getImportBatchNo());
        if (batch == null) {
            throw new BusinessException(PoseidonErrorCode.PAY_TRANS_BATCH_NOT_EXIST, "批次不存在");
        }
        OpenApiSafePayBatchResultQueryDto dto = new OpenApiSafePayBatchResultQueryDto();
        BeanCopierUtil.copy(batch, dto);
        //如果是最终状态 把批次详情也一起返回
        if (SafePayBatchStatus.isFinalStatus(batch.getStatus())) {
            List<SafePayOrder> orders = safePayOrderManager.listByBatchId(user.getId(), batch.getId());
            List<OpenApiSafePayOrderDto> orderDtos = BeanCopierUtil.batchCopy(SafePayOrder.class, OpenApiSafePayOrderDto.class, orders);
            dto.setOrders(orderDtos);
        }
        return new OpenApiResult<>(dto);
    }

    /**
     * 资金拨入账本
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/充值备付金")
    @ApiOperation(value = "资金拨入账本")
    @PostMapping("/charge")
    @ResponseBody
    public OpenApiResult<OpenApiSafePayChargeDto> chargeSafePayBook(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayChargeModel chargeModel = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayChargeModel.class);

        if (Strings.isNullOrEmpty(chargeModel.getAlipayNickName())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "请输入支付宝账号");
        }
        chargeModel.setAlipayNickName(chargeModel.getAlipayNickName().trim());
        if (!AlipayAccountCheckUtil.isEffectiveAccount(chargeModel.getAlipayNickName())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "支付宝账号格式错误");
        }

        User user = userManager.getById(openApp.getUserId());
        BookAccountChargeOrderModel model = new BookAccountChargeOrderModel();
        BeanCopierUtil.copy(chargeModel, model);
        BookAccountChargeOrder order = safePayService.createBookAccountChargeOrder(user, model);
        OpenApiSafePayChargeDto dto = new OpenApiSafePayChargeDto();
        dto.setPayUrl(order.getPayUrl());
        return new OpenApiResult<>(dto);
    }

    /**
     * 查询备付金充值记录
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/查询备付金充值记录")
    @ApiOperation(value = "查询备付金充值记录")
    @PostMapping("/query-charge-order")
    @ResponseBody
    public OpenApiResult<OpenApiSafePayChargeOrderQueryDto> queryChargeOrder(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayChargeOrderQueryModel model = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayChargeOrderQueryModel.class);
        if (Strings.isNullOrEmpty(model.getImportBizNo())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "商户外部订单号不能为空");
        }

        User user = userManager.getById(openApp.getUserId());
        BookAccountChargeOrder order = bookAccountChargeOrderManager.findByImportBizNo(user.getId(), model.getImportBizNo());
        OpenApiSafePayChargeOrderQueryDto dto = OpenApiSafePayChargeOrderQueryDto.getInstance();
        BeanCopierUtil.copy(order, dto);
        return new OpenApiResult<>(dto);
    }

    /**
     * 查询明细
     */
    @OpenApi
    @ApiMonitoring(value = "安全发/查询明细")
    @ApiOperation("查询明细")
    @PostMapping("/query-detail")
    public OpenApiResult<OpenApiSafePayDetailQueryDto> queryDetail(@RequestBody OpenApiProtocol openApiProtocol) {
        OpenApp openApp = openAppManager.getById(Long.valueOf(openApiProtocol.getAppId()));
        OpenApiSafePayDetailQueryModel queryModel = SerializationUtil.str2Object(openApiProtocol.getBizContent(), OpenApiSafePayDetailQueryModel.class);

        if (Strings.isNullOrEmpty(queryModel.getIdentity()) && Strings.isNullOrEmpty(queryModel.getImportBizNo())
                && Strings.isNullOrEmpty(queryModel.getImportBatchNo())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "收款方账号/订单编号/外部批次号 至少传其中一个参数");
        }

        User user = userManager.getById(openApp.getUserId());
        SafePayOrderSearchModel searchModel = SafePayOrderSearchModel.getInstance();
        searchModel.setUserId(user.getId());
        searchModel.setImportBatchNo(queryModel.getImportBatchNo());
        searchModel.setIdentity(queryModel.getIdentity());
        searchModel.setImportBizNo(queryModel.getImportBizNo());
        List<SafePayOrder> orders = safePayOrderManager.list(searchModel);
        List<OpenApiSafePayDetailQueryDto.SafePayDetail> details = BeanCopierUtil.batchCopy(SafePayOrder.class, OpenApiSafePayDetailQueryDto.SafePayDetail.class, orders);
        OpenApiSafePayDetailQueryDto dto = new OpenApiSafePayDetailQueryDto();
        dto.setOrders(details);
        return new OpenApiResult<>(dto);
    }
}
